#!/usr/bin/env python3
from intelhex import IntelHex
import sys
import os
import hashlib

def calculate_checksum(data):
    """计算数据的SHA256校验和"""
    return hashlib.sha256(data).hexdigest()

def merge_hex_files(boot_hex, app_hex, output_hex):
    """合并hex文件并添加校验"""
    print(f"Merging {boot_hex} and {app_hex}...")
    
    # 检查文件是否存在
    if not os.path.exists(boot_hex):
        raise FileNotFoundError(f"Bootloader hex file not found: {boot_hex}")
    if not os.path.exists(app_hex):
        raise FileNotFoundError(f"Application hex file not found: {app_hex}")
    
    # 读取hex文件
    ih_boot = IntelHex(boot_hex)
    ih_app = IntelHex(app_hex)
    
    # 获取地址范围
    boot_start = ih_boot.minaddr()
    boot_end = ih_boot.maxaddr()
    app_start = ih_app.minaddr()
    app_end = ih_app.maxaddr()
    
    print(f"Bootloader: 0x{boot_start:08X} - 0x{boot_end:08X}")
    print(f"Application: 0x{app_start:08X} - 0x{app_end:08X}")
    
    # 检查地址重叠
    if not (boot_end < app_start or app_end < boot_start):
        print("Warning: Address overlap detected!")
        print(f"Overlap: 0x{max(boot_start, app_start):08X} - 0x{min(boot_end, app_end):08X}")
    
    # 合并文件
    ih_boot.merge(ih_app, overlap='replace')
    
    # 计算校验和
    merged_data = ih_boot.tobinarray()
    checksum = calculate_checksum(merged_data)
    
    # 保存合并后的文件
    ih_boot.write_hex_file(output_hex)
    
    # 保存校验和
    checksum_file = output_hex + '.sha256'
    with open(checksum_file, 'w') as f:
        f.write(checksum)
    
    print(f"\nMerge complete!")
    print(f"Output file: {output_hex}")
    print(f"Checksum file: {checksum_file}")
    print(f"SHA256: {checksum}")
    
    # 计算总大小
    total_size = len(merged_data)
    print(f"Total size: {total_size} bytes ({total_size/1024:.2f} KB)")

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print("Usage: python merge_hex.py bootloader.hex app.hex output.hex")
        sys.exit(1)
    
    try:
        merge_hex_files(sys.argv[1], sys.argv[2], sys.argv[3])
    except Exception as e:
        print(f"Error: {str(e)}")
        sys.exit(1) 